/* 
 * File:   BasicCmd.cpp
 * Author: frank
 *
 * Created on 2013年10月23日, 下午8:57
 */

#include"FileMng.h"

//////////////////////////////////////////////////////////////////////////
//
//                                基本操作指令
//
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////
//
//                 Load File
//
/////////////////////////////////////
int loadFile(char *filename,short loadType,char *name)
{	
	int i,j,k,inode,memoNum;
	short size,sect;
	//查找该文件
	HeadIndex headIndex[INDEX_MAX];
	loadHeadIndex(headIndex);
        inode=getHeadNode(headIndex,filename);
        if(inode==FAIL){
            unloadHeadIndex(headIndex);
            return FAIL;
        }
        //权限审核
        // root和owner享有全权
        //与createFile的审核重复 
        if(strcmp(name,"root")!=0 && isOwner(name,filename)!=1){
            // 若loadType%PMS==0 则执行
            // 若loadType%PMS!=0 则无权访问
            if(loadType%headIndex[inode].PMS!=0){
                    printf("NO PERMISSION to execute %s!\n",filename);
                    unloadHeadIndex(headIndex);
                    return FAIL;
            }
        }
        
         //修改头索引
        if(loadType<=2){
                if(headIndex[inode].rdCnt>0 || headIndex[inode].wrtCnt>0){                
                        printf("File %s is BEING readed or writed, please try again later.\n",filename);
                        unloadHeadIndex(headIndex);
                        return FAIL;
                }
                else{
                        headIndex[inode].wrtCnt++;
                        //写回
                        unloadHeadIndex(headIndex);
                }
        }
        else{
                if(headIndex[inode].wrtCnt>0){
                        printf("File %s is BEING writed, please try again later.\n",filename);
                        return FAIL;
                }
                else{
                        headIndex[inode].rdCnt++;
                        //写回
                        unloadHeadIndex(headIndex);
                }
        }

        //插入打开文件表并装入内存
        while(openedSize+headIndex[inode].size>STRMEMO_MAX||openedSum==OPEN_MAX){
                printf("TOO MANY files have loaded, please unload some of them!\n");
                printf("Please input the file name to be unloaded:");
                cin>>filename;
                unloadFile(filename,name);
        }
        size=headIndex[inode].size;
        for(j=0;j<OPEN_MAX;j++){
                if(openFileMemo[j].access==FAIL){
                        openedSum++;
                        strcpy(openFileMemo[j].name,headIndex[inode].name);
                        openFileMemo[j].access=ACCESS;
                        openFileMemo[j].mod=0;
                        openFileMemo[j].loadType=loadType;
                        openFileMemo[j].size=size;
                        openFileMemo[j].type=headIndex[inode].type;
                        for(k=0;k<size;k++){
                                sect=headIndex[inode].sects[k];
                                memoNum=loadToMemo(sect);  //装入内存
                                openFileMemo[j].sectMemo[k][0]=sect;
                                openFileMemo[j].sectMemo[k][1]=memoNum;
                        }
                        break;

                }
        }
        return j;  //返回在openFileMemo表的位置


}

////////////////////////////////////////
//
//                 Create File
//
////////////////////////////////////////
int createFile(char *path,char *filename,char *name)
{
	char spms[5],strDir[50],temp[50];
	int vNum,i;
	char ctype;
	short type,pms,openNum,sect;
	long nowTime;
	HeadIndex headIndex[INDEX_MAX];

	//打开此路径
	openNum=loadFile(path,WRITE,name);
	if(openNum==FAIL){
		printf("Load directory FAILED!\n");
		return FAIL;
	}
	if(openFileMemo[openNum].type!=TYPE_DIR){
		printf("The directory that user input is NOT a directory file!\n");
		unloadFile(path,name);
		return FAIL;
	}
	
	//验证重复
	strcpy(temp,path);
	strcat(temp,"/");
	strcat(temp,filename);
	loadHeadIndex(headIndex);
	for(i=0;i<INDEX_MAX;i++){
		if(strcmp(headIndex[i].name,temp)==0){           
			printf("The file does exist ALREADY!\n");
                        unloadFile(path,name);
			//Do not unloadHeadIndex(headIndex);
                     
			return FAIL;
		}
	}
	unloadHeadIndex(headIndex);
	//分配磁盘空间
	vNum=loadFile("/vac",RANDW,"vac");
	if(vNum==FAIL){
		printf("load file /vac FAILED!\n");
                unloadFile(path,name);
		return FAIL;
	}
	sect=getVacSect(vNum);
	unloadFile("/vac",name);
	if(sect==FAIL){
		printf("There is NO ROOM in the harddisk!\n");
		unloadFile(path,name);
		return FAIL;
	}

	printf("Please input the type of the file\n([d]Directory File [f]Normal File):");
	while(1){
		cin>>ctype;
		if(ctype=='d'){ 
			type=TYPE_DIR; 
			break;
		}else if(ctype=='f'){
			type=TYPE_FILE;
			break;
		}else{
			printf("The value you entered is NOT valid, please input again!\n");
		}
	} 
        
        if(type==TYPE_DIR){
            pms=READ;
            strcpy(spms,"r");
        }
        else{
            printf("Please choose the permission accredited to other users\n");
            printf("([r]READ ONLY [w]WRITE ONLY [rw]READ AND WRITE [no]NONE):");
            while(1){
                    cin>>spms;
                    if(strcmp(spms,"rw")==0){ 
                            pms=RANDW; 
                            break;
                    }else if(strcmp(spms,"r")==0){
                            pms=READ;
                            break;
                    }else if(strcmp(spms,"w")==0){
                            pms=WRITE;
                            break;
                    }else if(strcmp(spms,"no")==0){
                            pms=NONE;
                            break;
                    }else{
                            printf("The value you entered is NOT valid, please input again!\n");
                    }
            } 
        }
	
	time(&nowTime);
	
	strDir[0]='\0';
	buildDir(strDir,filename,spms,ctype,nowTime);
	appendContent(strDir,openNum,name);
	unloadFile(path,name);

	loadHeadIndex(headIndex);
	
	strcat(path,"/");
	strcat(path,filename);

	addHead(headIndex,path,pms,sect,type,1,nowTime);
	unloadHeadIndex(headIndex);
	
	//loadHeadIndex(headIndex);

	return SUCCESS;
}

////////////////////////////////////////////
//
//                 Unload File
//
////////////////////////////////////////////
int unloadFile(char *filename,char*name)
{
	int i,j,k,vNum,sect;
	HeadIndex headIndex[INDEX_MAX];
	long nowTime;
	short oSize,hSize,sectNum,memoNum,size;

	//在打开文件表中查找此文件  
	for(i=0;i<OPEN_MAX;i++){
            if(strcmp(openFileMemo[i].name,filename)==0){
                    //判断此文件是否读脏
                    if(openFileMemo[i].mod==1){ //读脏
                            time(&nowTime);
                            oSize=openFileMemo[i].size;
                            loadHeadIndex(headIndex);
                            j=getHeadNode(headIndex,filename);
                            hSize=headIndex[j].size;
                            if(oSize<hSize){
                                    vNum=loadFile("/vac",RANDW,"vac");
                                    if(vNum==FAIL){
                                            printf("load file /vac FAILED!\n");
                                            unloadHeadIndex(headIndex);
                                            return FAIL;
                                    }
                                    for(k=oSize;k<hSize;k++){
                                            delSect(vNum,headIndex[j].sects[k]);
                                    }
                                    unloadFile("/vac",name);
                            }
                            else if(oSize>hSize){
                                    vNum=loadFile("/vac",RANDW,"vac");
                                    if(vNum==FAIL){
                                            printf("load file /vac FAILED!\n");
                                            unloadHeadIndex(headIndex);
                                            return FAIL;
                                    }
                                    for(k=hSize;k<oSize;k++){
                                            while(1){
                                            sect=getVacSect(vNum);
                                            if(sect==FAIL){
                                                    printf("There is NO ROOM in the harddisk, please delete some of them!\n");
                                                    printf("Please input the file name to be deleted:");
                                                    cin>>filename;
                                                    deleteFile(filename,name);
                                            }
                                            else
                                                    break;
                                            }
                                            openFileMemo[i].sectMemo[k][0]=sect;
                                            headIndex[j].sects[k]=sect;
                                            headIndex[j].size=headIndex[j].size+1;
                                    }
                                    unloadFile("/vac",name);
                            }
                            for(k=0;k<oSize;k++){
                                    sectNum=openFileMemo[i].sectMemo[k][0];
                                    memoNum=openFileMemo[i].sectMemo[k][1];
                                    writeBack(strMemo[memoNum],sectNum);
                                    unloadMemo(memoNum);
                            }
                            headIndex[j].modTime=nowTime;
                            headIndex[j].size=oSize;
                            headIndex[j].wrtCnt--;
                            unloadHeadIndex(headIndex);
                    }
                    else{  //未读脏
                            size=openFileMemo[i].size;
                            for(j=0;j<size;j++){
                                    memoNum=openFileMemo[i].sectMemo[j][1];
                                    unloadMemo(memoNum);
                            }

                            loadHeadIndex(headIndex);
                            if(openFileMemo[i].loadType<=2){
                                    for(j=0;j<INDEX_MAX;j++){
                                            if(strcmp(headIndex[j].name,filename)==0){
                                                    headIndex[j].wrtCnt--;
                                                    break;
                                            }
                                    }
                            }
                            else{
                                    for(j=0;j<INDEX_MAX;j++){
                                            if(strcmp(headIndex[j].name,filename)==0){
                                                    headIndex[j].rdCnt--;
                                                    break;
                                            }
                                    }
                            }
                            unloadHeadIndex(headIndex);
                    }
                    openFileMemo[i].access=FAIL;
                    strcpy(openFileMemo[i].name,"\0");
                    openedSum--;
                    
                    return SUCCESS;  
            }
	}
	printf("The file has NOT been load!\n");
	return FAIL;
}


///////////////////////////////////////
//
//    			Delete File
//
///////////////////////////////////////
int deleteFile(char *filename,char *name)
{
	int i,j,n,temp,inode;
	short size,vNum;
	char tempBuff[50],affirm;
	HeadIndex headIndex[INDEX_MAX];
        
        int fileOpenNum,dirOpenNum,memoNum;
        char dir[50],file[20],stream[CONTENT_MAX];

	cout<<"\n**********************************\n";
	cout<<"    CONFIRM:[Y]Delete [N]Cancel";
	cout<<"\n**********************************\n";
	while(1){
		cin>>affirm;
		if(affirm=='y' || affirm=='Y')
			break;
		else if(affirm=='n'|| affirm=='N')
			return FAIL;
		else
			printf("The value you entered is NOT valid, please input again:");
	}
  
        //divide dir and file
        n=strlen(filename);
        strcpy(dir,filename);
	for(i=n-1;i>=0;i--){
		if(dir[i]=='/'){
			if(i!=0)
				dir[i]='\0';
			break;
		}
	}
	j=0;
	temp=i;
	for(i=i+1;i<n;i++){
		file[j]=dir[i];
		j++;
	}
	file[j]='\0';
	dir[temp+1]='\0';
        
        
        fileOpenNum=loadFile(filename,RANDW,name);
        dirOpenNum=loadFile(dir,RANDW,name);
        if(fileOpenNum==FAIL){
            if(dirOpenNum!=FAIL) unloadFile(dir,name);
            return FAIL;
        }
        if(dirOpenNum==FAIL){
            unloadFile(filename,name);
            return FAIL;
        }
        memoNum=openFileMemo[fileOpenNum].sectMemo[0][1];        
        strcpy(stream,strMemo[memoNum]);
        if(strcmp(stream,"-------")!=0){
            printf("The directory is NOT empty!\n");
            unloadFile(dir,name);
            unloadFile(filename,name);
            return FAIL;
        }
     
        //改头索引
        loadHeadIndex(headIndex);
        inode=getHeadNode(headIndex,filename);     
        strcpy(headIndex[inode].name,"\0");
        headIndex[inode].type=TYPE_NONE;
        size=headIndex[inode].size;
        unloadHeadIndex(headIndex);

        //在上一层的目录文件中删除该文件信息
        delFileInDir(dirOpenNum,file,name);
        unloadFile(dir,name);

        //撤销磁盘空间and memo
        vNum=loadFile("/vac",RANDW,"vac");
        while(vNum==FAIL){
                printf("load file /vac FAILED! Please try again.\n");
                cin>>tempBuff;
        }
        for(j=0;j<size;j++){
                delSect(vNum,headIndex[inode].sects[j]);
                unloadMemo(openFileMemo[fileOpenNum].sectMemo[j][1]);
        }
        unloadFile("/vac",name);
        openFileMemo[fileOpenNum].access=FAIL;
        strcpy(openFileMemo[fileOpenNum].name,"\0");
        openedSum--;
        return SUCCESS;
}


////////////////////////////////////////
//
//               Show File
//
////////////////////////////////////////
int showFile(char *filename)
{
	int i,j;
	short size,memoNum;

	for(i=0;i<INDEX_MAX;i++){
		if(strcmp(openFileMemo[i].name,filename)==0){
			if(openFileMemo[i].loadType==WRITE){
				printf("The load type does NOT match!\n");
				return FAIL;
			}

			size=openFileMemo[i].size;
			for(j=0;j<size;j++){
				memoNum=openFileMemo[i].sectMemo[j][1];
				cout<<strMemo[memoNum];
			}
			printf("\n");
			return SUCCESS;
		}
	}
	printf("Please load the file with READ ONLY or READ AND WRITE type before!\n");
	return FAIL;
}


////////////////////////////////////////////
//
//				     Edit File
//
///////////////////////////////////////////
int editFile(char *filename,char*name)
{
	int i,type;
	short loadType;
	char newStream[CONTENT_MAX*SECT_MAX-SECT_MAX];

	printf("Please input the number of type of edit:\n");
	printf("1.Edit freely(type of loading should be READ AND WRITE)\n");
	printf("2.Replace\n");
	printf("3.Append\n");
	printf("Number:");
	while(1){
		cin>>type;
		if(type>4||type<1)
			printf("The value you entered is NOT valid, please input again!!\n");
		else
			break;
	}

	for(i=0;i<INDEX_MAX;i++){
		if(strcmp(openFileMemo[i].name,filename)==0){
                        if(openFileMemo[i].type==TYPE_DIR){
                            cout<<"NO PERMISSION to edit a directory!";
                            return FAIL;
                        }
                    
			//检测打开方式
			loadType=openFileMemo[i].loadType;
			if(loadType==3 || type<loadType){
				printf("The load type does NOT match!\n");
				return FAIL;
			}

			if(type==1){
				printf("Previous content:\n");
				showFile(filename);
				printf("\n\nPlease input new content:\n");
				cin>>newStream;
				replaceContent(newStream,i,name);		
			}
			else if(type==2){
				printf("Please input new content(less than %d characters):\n",CONTENT_MAX*SECT_MAX-SECT_MAX);
				cin>>newStream;
				replaceContent(newStream,i,name);
			}
			else{
				printf("Please input content appending(less than %d characters):\n",CONTENT_MAX*SECT_MAX-SECT_MAX);
				cin>>newStream;
				appendContent(newStream,i,name);
			}
			return SUCCESS;
		}
	}
	printf("Please load the file with WRITE ONLY or READ AND WRITE type before!!\n");
	return FAIL;
}


